package com.logica.mdm.webfrontend.embedding;

import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;

import com.logica.mdm.webfrontend.utils.URLUtils;

/**
 * Embedding interceptor, used to define which embedding adapter to use
 * for application integration.
 * @author Fabien Crespel <fabien.crespel@logica.com>
 */
public class EmbeddingInterceptor extends HandlerInterceptorAdapter {

	public static final String DEFAULT_PARAM_NAME = "embedding";
	
	private String paramName = DEFAULT_PARAM_NAME;
	private String pathMatchingRegex = null;
	private Pattern pathMatchingPattern = null;
	
	@Autowired
	private List<EmbeddingAdapter> embeddingAdapters;
	
	@Autowired
	private EmbeddingResolver embeddingResolver;

	public String getParamName() {
		return this.paramName;
	}

	public void setParamName(String paramName) {
		this.paramName = paramName;
	}
	
	public String getPathMatchingRegex() {
		return this.pathMatchingRegex;
	}
	
	public void setPathMatchingRegex(String pathMatchingRegex) {
		this.pathMatchingRegex = pathMatchingRegex;
		this.pathMatchingPattern = null;
	}
	
	protected Pattern getPathMatchingPattern() {
		if (this.pathMatchingPattern == null && getPathMatchingRegex() != null) {
			this.pathMatchingPattern = Pattern.compile(getPathMatchingRegex());
		}
		return this.pathMatchingPattern;
	}
	
	/**
	 * Get the embedding adapter name out of the HTTP servlet request.
	 * This will first try to get the adapter name from a request parameter,
	 * then from a path regex match (if possible).
	 * @param request
	 * @return
	 */
	protected String getAdapterName(HttpServletRequest request) {
		String adapterName = request.getParameter(this.paramName);
		if (adapterName == null && getPathMatchingPattern() != null) {
			String relativePath = URLUtils.getRequestURIWithoutContext(request);
			Matcher matcher = getPathMatchingPattern().matcher(relativePath);
			if (matcher.matches()) {
				adapterName = matcher.group(1);
			}
		}
		return adapterName;
	}

	@Override
	public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
			throws Exception {
		
		String adapterName = getAdapterName(request);
		if (adapterName != null) {
			EmbeddingAdapter embeddingAdapter = null;
			for (EmbeddingAdapter adapter : embeddingAdapters) {
				if (adapterName.equals(adapter.getName())) {
					embeddingAdapter = adapter;
					break;
				}
			}
			if (embeddingAdapter != null) {
				embeddingResolver.setEmbeddingAdapter(request, response, embeddingAdapter);
			}
		}
		
		return true;
	}
}
